/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.model;

import com.caracol.crypto.SingletonPassword;
import com.caracol.db.CaracolQueryGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Vector;

/**
 * Class is used to represent a user and also the defualt
 * operations that are aviable in the database CRUD operations.
 * 
 * @author Roque Rueda
 */
public class Usuario {

    private static CaracolQueryGenerator caracolQuery = new CaracolQueryGenerator();
    private int id;
    private String usuario;
    private String contrasena;
    private String nombre;
    /***
     * Name of the id colum in the database
     */
    public static final String ID = "id";
    /***
     * Name of the usuario colum in the database
     */
    public static final String USUARIO = "usuario";
    /***
     * Name of the nombre colum in the database
     */
    public static final String NOMBRE = "nombre";
    /***
     * Name of the contrasena colum in the database
     */
    public static final String CONTRASENA = "contrasena";
    /***
     * Name of the table in the database
     */
    public static final String TABLE = "usuarios";

    /**
     * Default constructor wich creates an instance
     * with the default values
     */
    public Usuario() {
        this(0, "", "", "");
    }

    /**
     * Creates an instance with the given values
     * @param id User id this comes from database
     * @param usuario this is the String nickname that is used in the login
     * @param contrasena this is the password and is hashed
     * @param nombre this is the real name of the user
     */
    private Usuario(int id, String usuario, String contrasena, String nombre) {
        this.id = id;
        this.usuario = usuario;
        this.contrasena = contrasena;
        this.nombre = nombre;
    }
    
    /**
     * Creates an instance with the given values
     * @param usuario this is the String nickname that is used in the login
     * @param contrasena this is the password and is hashed
     * @param nombre this is the real name of the user
     */
    public Usuario(String usuario, String contrasena, String nombre){
        this(0, usuario, contrasena, nombre);
    }

    /**
     * Gets the user by his given id
     * @param id Id to search for in the database
     * @return User instance if finds the id otherwise null
     */
    public static Usuario getUsuario(int id) throws Exception {
        StringBuilder sb = new StringBuilder("SELECT " + ID + ",");
        sb.append(USUARIO + "," + CONTRASENA + "," + NOMBRE + " FROM ");
        sb.append(TABLE + " WHERE " + ID + " = ").append(id);
        ArrayList<Object> resultset = new ArrayList<Object>(caracolQuery.executeQuery(sb.toString()));
        if (resultset != null && resultset.size() > 0) {
            Vector<Object> row = (Vector<Object>) resultset.get(0);
            // something has come back from the data acess class
            String usuario = row.elementAt(1).toString();
            String contrasena = row.elementAt(2).toString();
            String nombre = row.elementAt(3).toString();
            Usuario usr = new Usuario(id, usuario, contrasena, nombre);
            return usr;
        }
        return null;
    }

    /**
     * Seach for a specific user by his user and his password
     * @param usuario user name
     * @param contrasena password
     * @return User instance if it's find in the database otherwise null
     */
    public static Usuario login(String usuario, String contrasena) throws NoSuchAlgorithmException, Exception {
        StringBuilder sb = new StringBuilder("SELECT " + ID + ",");
        sb.append(USUARIO + "," + CONTRASENA + "," + NOMBRE + " FROM ");
        sb.append(TABLE + " WHERE " + USUARIO + " = \'").append(usuario).append("\'");
        sb.append(" AND " + CONTRASENA + " = \'").append(SingletonPassword.getInstance().encrypt(contrasena)).append("\'");
        ArrayList<Object> resultset = new ArrayList<Object>(caracolQuery.executeQuery(sb.toString()));
        if (resultset != null && resultset.size() > 0) {
            Vector<Object> row = (Vector<Object>) resultset.get(0);
            Double tem = Double.parseDouble(row.elementAt(0).toString());
            int id = tem.intValue();
            String usuarioResult = row.elementAt(1).toString();
            String contrasenaResult = row.elementAt(2).toString(); // this is risk
            String nombre = row.elementAt(3).toString();
            Usuario usr = new Usuario(id, usuarioResult, contrasenaResult, nombre);
            return usr;
        }
        return null;
    }

    /***
     * Saves this object in the data base
     * @return true if is save or it is already saved otherwise false
     */
    public boolean save() throws Exception {
        if(getId() > 0){
            return true;
        }
        
        StringBuilder sb = new StringBuilder("INSERT INTO " + TABLE + "(");
        sb.append(USUARIO + "," + CONTRASENA + "," + NOMBRE + ") VALUES (");
        sb.append("\'").append(getUsuario()).append("\', \'");
        sb.append(SingletonPassword.getInstance().encrypt(getContrasena()));
        sb.append("\', \'").append(getNombre()).append("\');");
        int rowsAffected = caracolQuery.executeCommandLeaveOpenConnection(sb.toString());
        ArrayList<Object> dataset = null;
        if (rowsAffected > 0) {
            sb = new StringBuilder("SELECT currval(\'squsuarios\');");
            dataset = new ArrayList<Object>(caracolQuery.executeQuery(sb.toString()));
        }
        if (dataset != null && dataset.size()>0) {
            Vector<Object> row = (Vector<Object>) dataset.get(0);
            Double tem = Double.parseDouble(row.elementAt(0).toString());
            this.id = tem.intValue();
            return true;
        }
        return false;
    }

    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @return the usuario
     */
    public String getUsuario() {
        return usuario;
    }

    /**
     * @param usuario the usuario to set
     */
    public void setUsuario(String usuario) {
        this.usuario = usuario;
    }

    /**
     * @return the contrasena
     */
    public String getContrasena() {
        return contrasena;
    }

    /**
     * @param contrasena the contrasena to set
     */
    public void setContrasena(String contrasena) {
        this.contrasena = contrasena;
    }

    /**
     * @return the nombre
     */
    public String getNombre() {
        return nombre;
    }

    /**
     * @param nombre the nombre to set
     */
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
}
